 
import qs from 'qs'
export default class Cache {
	constructor(axios, config = {}) {
		this.axios = axios
		this.caches = []
		if (!this.axios) {
			throw new Error('请传入axios实例')
		}
		this.config = config
		this.defaultConfig = {
			showLoading: false,
			cache: false,
			expire: 100 * 1000
		}
		this.CancelToken = this.axios.CancelToken
		this.init()
	}
	init() {
		this.requestInterceptor(this.config.requestInterceptorFn)
		this.responseInterceptor(this.config.responseInterceptorFn)
		// window.onbeforeunload = () => {
		//   this.mapStorage()
		// }
	}
	requestInterceptor(callback) {
		this.axios.interceptors.request.use(async config => {
			let newConfig = callback && (await callback(config))
			config = newConfig || config
			let {
				url,
				data,
				params,
				cache = this.defaultConfig.cache,
				expire = this.defaultConfig.expire
			} = config
			if (cache === true) {
				let getKey = data ? `${url}?cacheParams=${JSON.stringify(data)}` :
					`${url}?cacheParams=${qs.stringify(params)}`
				let obj = this.getStorage(getKey)
				// 判断缓存数据是否存在
				if (obj) {
					let curTime = this.getExpireTime()
					let source = this.CancelToken.source()
					config.cancelToken = source.token
					// 判断缓存数据是否存在，存在的话是否过期，如果没过期就停止请求返回缓存
					if (curTime - obj.expire < expire) {
						source.cancel(obj)
					} else {
						this.removeStorage(url)
					}
				}
			} else {
				// this.clearStorage(url)
				this.removeStorage(url)
			}
			return config
		}, error => {
			return Promise.reject(error)
		})
	}
	responseInterceptor(callback) {
		this.axios.interceptors.response.use(async response => {
			let newResponse = callback && (await callback(response))
			response = newResponse || response
			// the http request error, do not store the result, direct return result
			if (response.status !== 200) {
				return response
			}
			/*
			 * `data` is the data to be sent as the request body, only applicable for request methods 'PUT', 'POST', and 'PATCH'
			 * `params` are the URL parameters to be sent with the request, can be applicable for request methods 'GET'
			 */
			let {
				url,
				cache,
				data,
				params
			} = response.config
			if (cache === true) {
				let obj = {
					expire: this.getExpireTime(),
					params,
					data,
					result: response.data
				}
				let setKey = data ? `${url}?cacheParams=${data}` : `${url}?cacheParams=${qs.stringify(params)}`
				this.caches.push(setKey)
				this.setStorage(setKey, obj)
			}
			return response.data
		}, async error => {
			let newError = callback && (await callback(newError))
			error = newError || error
			// 返回缓存数据
			if (this.axios.isCancel(error)) {
				return Promise.resolve(error.message.result)
			}
			return Promise.reject(error)
		})
	}

	// 設置缓存
	setStorage(key, cache) {
		uni.setStorageSync(key, cache)
	}

	// 获取缓存
	getStorage(key) {
		const data = uni.getStorageSync(key)
		return data
	}

	// 清除缓存
	removeStorage(key) {
		uni.removeStorageSync(key)
	}

	// 設置过期時間
	getExpireTime() {
		return new Date().getTime()
	}

	// 清空缓存
	clearStorage() {
		uni.clearStorageSync()
	}

	// 清空没用到的缓存
	mapStorage() {
		const res = uni.getStorageInfoSync()
		const length = res.keys.length
		if (length) {
			for (let i = 0; i < length; i++) {
				const key = res.keys[i]
				if (!this.caches.includes(key) && key.includes('?cacheParams=')) {
					uni.removeStorageSync(key)
				}
			}
		}
	}
}
